package com.dream.technology.service.impl;

import com.dream.technology.components.riskControl.SymbolAnalysis;
import com.dream.technology.components.riskControl.SymbolConstan;
import com.dream.technology.components.riskControl.tianji.RcConstan;
import com.dream.technology.db.dao.RcRuleCollectionMapper;
import com.dream.technology.db.entity.*;
import com.dream.technology.db.entity.vo.VoRuleAll;
import com.dream.technology.db.entity.vo.VoRuleCollection;
import com.dream.technology.db.entity.vo.VoRuleCollectionAll;
import com.dream.technology.service.*;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service("rcRuleCollectionService")
public class RcRuleCollectionServiceImpl implements RcRuleCollectionService {

    private static final Logger logger = LoggerFactory.getLogger(RcRuleCollectionService.class);
    @Autowired
    RcRuleCollectionMapper rcRuleCollectionMapper;
    //    @Autowired
//    RcRuleCollectionItemMapper rcRuleCollectionItemMapper;
    @Autowired
    RcRuleCollectionItemService rcRuleCollectionItemService;
    @Autowired
    RcRuleService rcRuleService;
    @Autowired
    RcRuleItemService rcRuleItemService;
    @Autowired
    SymbolAnalysis symbolAnalysis;
   /* @Autowired
    private AdminClient adminClient;*/
    @Autowired
    private RcFlowItemService rcFlowItemService;


    @Override
    public int countByExample(RcRuleCollectionQuery example) {
        return rcRuleCollectionMapper.countByExample(example);
    }

    @Override
    @Transactional
    public int deleteByExample(RcRuleCollectionQuery example) {
        return rcRuleCollectionMapper.deleteByExample(example);
    }

    @Override
    @Transactional
    public int deleteByPrimaryKey(Long id) {
        return rcRuleCollectionMapper.deleteByPrimaryKey(id);
    }

    @Override
    @Transactional
    public int insert(RcRuleCollection record) {
        return rcRuleCollectionMapper.insert(record);
    }

    @Override
    @Transactional
    public String insertStr(VoRuleCollection voRuleCollection) {

        logger.debug("addCustomerTagSetting str ========{}", voRuleCollection);
        //获取管理员id
        /*GenericRspDTO<OperationAdmin> userInfo = adminClient.getUserInfoByToken();
        Integer id = userInfo.getBody().getId();
        String userName = userInfo.getBody().getUserName();
        String riskControlClaCode = RandomCode.getRiskControlClaCode();*/
        RcRuleCollection rcRuleCollection = voRuleCollection.getRcRuleCollection();
        List<RcRuleCollectionItem> rcRuleCollectionItems = voRuleCollection.getRcRuleCollectionItem();
//        rcRuleCollection.setAdminId(Long.valueOf(id));
//        rcRuleCollection.setCreator(userName);
//        rcRuleCollection.setCollectionCode(riskControlClaCode);
        String desc = checkRuleCollection(voRuleCollection);
        rcRuleCollection.setCollectionRuleDesc(desc);
        rcRuleCollection.setStatus(false);
        insert(rcRuleCollection);
        ArrayList<RcRuleCollectionItem> tagItems = new ArrayList<>();
        rcRuleCollectionItems.forEach(rcRuleCollectionItem -> {
            rcRuleCollectionItem.setCollectionId(rcRuleCollection.getId());
            tagItems.add(rcRuleCollectionItem);
        });
        rcRuleCollectionItemService.insertList(tagItems);
        return "success";

    }

    @Override
    @Transactional
    public int insertSelective(RcRuleCollection record) {
        return rcRuleCollectionMapper.insertSelective(record);
    }

    @Override
    public List<RcRuleCollection> selectByExample(RcRuleCollectionQuery example) {
        return rcRuleCollectionMapper.selectByExample(example);
    }

    @Override
    public RcRuleCollection selectByPrimaryKey(Long id) {
        return rcRuleCollectionMapper.selectByPrimaryKey(id);
    }

    @Override
    @Transactional
    public int updateByExampleSelective(RcRuleCollection record, RcRuleCollectionQuery example) {
        return rcRuleCollectionMapper.updateByExampleSelective(record, example);
    }

    @Override
    @Transactional
    public int updateByExample(RcRuleCollection record, RcRuleCollectionQuery example) {
        return rcRuleCollectionMapper.updateByExample(record, example);
    }

    @Override
    @Transactional
    public int updateByPrimaryKeySelective(RcRuleCollection record) {
        return rcRuleCollectionMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    @Transactional
    public int updateByPrimaryKey(RcRuleCollection record) {
        return rcRuleCollectionMapper.updateByPrimaryKey(record);
    }

    /**
     * 检查规则集设置
     *
     * @param voRuleCollection
     * @return
     */
    @Override
    public String checkRuleCollection(VoRuleCollection voRuleCollection) {
        logger.info("checkruleCollectionSetting str ========{}", voRuleCollection);
//        //规则items

//        //规则集表达式
        RcRuleCollection rcRuleCollection = voRuleCollection.getRcRuleCollection();
        List<RcRuleCollectionItem> rcRuleCollectionItems = voRuleCollection.getRcRuleCollectionItem();
        Map<Long, String> rulesMap = new HashMap<>(rcRuleCollectionItems.size() << 1);
        ArrayList<Long> ruleIds = new ArrayList<>();
        //记录规则别名
        rcRuleCollectionItems.forEach(item -> {
            ruleIds.add(item.getRuleId());
            rulesMap.put(item.getRuleId(), item.getItemAlias());
        });
        List<RcRule> rcRules = rcRuleService.selectByIdInList(ruleIds);
        Map<String, String> rulesAnalsMap = new HashMap<>(rcRuleCollectionItems.size() << 1);
        rcRules.forEach(ru -> {
            // 重新映射 别名与描述
            String ruleAn = rulesMap.get(ru.getId());
            rulesAnalsMap.put(ruleAn, ru.getRuleDesc());
        });

        return symbolAnalysis.getExp(rcRuleCollection.getCollectionRule(), rulesAnalsMap);
    }

    /**
     * 复制规则集
     *
     * @param id
     * @param name
     * @param code
     * @return
     */
    @Override
    @Transactional
    public String copy(Long id, String collectionName, String collectionDetail, Boolean enabled) {
        RcRuleCollection ruleCollection = rcRuleCollectionMapper.selectByPrimaryKey(id);
//        ruleCollection.setCollectionCode(RandomCode.getRiskControlClaCode());
        ruleCollection.setId(null);
        ruleCollection.setCollectionName(collectionName);
        ruleCollection.setCollectionDetail(collectionDetail);
        ruleCollection.setEnabled(enabled);
        ruleCollection.setCreateDate(new Date());
        insert(ruleCollection);
        //复制子项
        rcRuleCollectionItemService.copy(id, ruleCollection.getId());
        return RcConstan.SUCCESS;
    }

    /**
     * 根据json修改规则集
     *
     * @param
     * @return
     */
    @Override
    @Transactional
    public String updateByJsonStr(VoRuleCollection voRuleCollection) {
        logger.info("updateByJsonStr str ========{}", voRuleCollection);
        // 前端传回来的规则集
        RcRuleCollection rcRuleCollection = voRuleCollection.getRcRuleCollection();
        // 原规则集
        RcRuleCollection rcRuleCollectionOld = rcRuleCollectionMapper.selectByPrimaryKey(rcRuleCollection.getId());
        List<RcRuleCollectionItem> rcRuleCollectionItems = voRuleCollection.getRcRuleCollectionItem();
        //规则描述
        String desc = checkRuleCollection(voRuleCollection);
        rcRuleCollection.setCollectionRuleDesc(desc);
        updateByPrimaryKeySelective(rcRuleCollection);

        List<RcRuleCollectionItem> collectionItems = rcRuleCollectionItemService.selectByCollectionId(rcRuleCollection.getId());
        ArrayList<Long> itemIds = new ArrayList<>();
        rcRuleCollectionItems.forEach(item -> {
            if (item.getId() != null) {
                rcRuleCollectionItemService.updateByPrimaryKeySelective(item);
                itemIds.add(item.getId());
            } else {
                item.setCollectionId(rcRuleCollection.getId());
                rcRuleCollectionItemService.insertSelective(item);
            }
        });
        // delete
        List<RcRuleCollectionItem> deleteItems = collectionItems.stream().filter(item -> !itemIds.contains(item.getId())).collect(Collectors.toList());
        deleteItems.forEach(item -> rcRuleCollectionItemService.deleteByPrimaryKey(item.getId()));
        // 修改规则集名称，需要同步子流程中引用的此规则集的名称
  		if (!rcRuleCollectionOld.getCollectionName().equals(rcRuleCollection.getCollectionName())) {
  			// 查询引用此规则集的子流程
  			RcFlowItemQuery flowItemQuery = new RcFlowItemQuery();
  			RcFlowItemQuery.Criteria criteria = flowItemQuery.createCriteria();
  			criteria.andChildItemIdEqualTo(rcRuleCollectionOld.getId());
  			criteria.andChildItemTypeEqualTo(2);
  			List<RcFlowItem> flowItemList = rcFlowItemService.selectByExample(flowItemQuery);
  			if (CollectionUtils.isNotEmpty(flowItemList)) {
  				for (RcFlowItem item : flowItemList) {
  					RcFlowItem itemNew = new RcFlowItem();
  					itemNew.setId(item.getId());
  					itemNew.setChildItemName(rcRuleCollection.getCollectionName());
  					rcFlowItemService.updateByPrimaryKeySelective(itemNew);
  				}
  			}
  		}
        return null;
    }


    /**
     * 查询组装 flow 的某个部分
     *
     * 为避免流程运行时多次查询 集中查询手动映射
     *
     *
     * @param items
     * @return
     */
    @Override
    public Map<String, Map<RcFlowItem, Object>> getVoRuleCollAll(List<RcFlowItem> items) {

        // 获取所有规则集id
        List<Long> collectIds = new ArrayList<>();
        items.stream().filter(item -> item.getChildItemType().equals(Integer.valueOf(SymbolConstan.FLOW_ITEM_TYPE_COLL)))
                .forEach(item -> collectIds.add(item.getChildItemId()));

        // 获取所有的规则id
//        List<Long> ruleIds   = new ArrayList<>();
        List<Long> ruleIds  = items.stream().filter(item -> item.getChildItemType().equals(Integer.valueOf(SymbolConstan.FLOW_ITEM_TYPE_RULE)))
                .map(RcFlowItem::getChildItemId).collect(Collectors.toList());

        // 查询规则规则集
        RcRuleCollectionQuery query = new RcRuleCollectionQuery();
        query.createCriteria().andIdIn(collectIds);
        List<RcRuleCollection> rcRuleCollections = rcRuleCollectionMapper.selectByExample(query);
        Map<Long, RcRuleCollection> collectionMap = rcRuleCollections.stream().collect(Collectors.toMap(RcRuleCollection::getId, x -> x));

        // 规则集元素
        RcRuleCollectionItemQuery itemQuery = new RcRuleCollectionItemQuery();
        itemQuery.createCriteria().andCollectionIdIn(collectIds);
        List<RcRuleCollectionItem> collectionItems = rcRuleCollectionItemService.selectByExample(itemQuery);

        //查询所有规则
        List<Long> ids = new ArrayList<>(ruleIds);
        ids.addAll(collectionItems.stream().map(RcRuleCollectionItem::getRuleId).collect(Collectors.toList()));
//        collectionItems.forEach(item -> ids.add(item.getRuleId()));
        RcRuleQuery ruleQuery = new RcRuleQuery();
        ruleQuery.createCriteria().andIdIn(ids);
        List<RcRule> rcRules = rcRuleService.selectByExample(ruleQuery);
        //查询rule item
        RcRuleItemQuery ruleItemQuery = new RcRuleItemQuery();
        ruleItemQuery.createCriteria().andRuleIdIn(ids);
        List<RcRuleItem> rcRuleItems = rcRuleItemService.selectByExample(ruleItemQuery);

        // 创建ruleid 与rule的映射
//        Map<Long, RcRule> ruleIdMap = new HashMap<>();
//        rcRules.forEach(rcRule -> ruleIdMap.put(rcRule.getId(), rcRule));
        Map<Long, RcRule> ruleIdMap = rcRules.stream().collect(Collectors.toMap(RcRule::getId, x -> x));
        //映射voruleall 对象
        Map<Long, VoRuleAll> ruleItemsMap = getLongListMap(rcRuleItems, ruleIdMap);

        //映射规则集与规则item
        Map<Long, List<RcRuleCollectionItem>> collItemMap = getCollItemMap(collectionItems);
        //获取 VoRuleCollectionAll 与规则集id的映射关系
        Map<Long, VoRuleCollectionAll> collectionAllMaps = getVoCollRuleAll(collectionMap, ruleItemsMap, collItemMap);

        // zh
        Map<String, Map<RcFlowItem, Object>> flowMap = getFlowMap(items, ruleItemsMap, collectionAllMaps);


        return flowMap;
    }

    /**
     * 组装flowMap
     * @param items
     * @param ruleItemsMap
     * @param collectionAllMaps
     * @return
     */
    public Map<String, Map<RcFlowItem, Object>> getFlowMap(List<RcFlowItem> items, Map<Long, VoRuleAll> ruleItemsMap, Map<Long, VoRuleCollectionAll> collectionAllMaps) {
        Map<String, Map<RcFlowItem, Object>> flowMap = new HashMap<>();
        items.forEach(x ->{
            Map<RcFlowItem, Object> itemObjectMap = new HashMap<>();
            if (x.getChildItemType().equals(Integer.valueOf(SymbolConstan.FLOW_ITEM_TYPE_COLL))){
                itemObjectMap.put(x,collectionAllMaps.get(x.getChildItemId()));
            }else if    (x.getChildItemType().equals(Integer.valueOf(SymbolConstan.FLOW_ITEM_TYPE_RULE))){
                itemObjectMap.put(x,ruleItemsMap.get(x.getChildItemId()));
            }
            flowMap.put(x.getItemAlias(),itemObjectMap);
        });
        return flowMap;
    }

    /**
     * 获取 VoRuleCollectionAll 与规则集id的映射关系
     * @param collectionMap
     * @param ruleItemsMap
     * @param collItemMap
     * @return
     */
    public Map<Long, VoRuleCollectionAll> getVoCollRuleAll(Map<Long, RcRuleCollection> collectionMap, Map<Long, VoRuleAll> ruleItemsMap, Map<Long, List<RcRuleCollectionItem>> collItemMap) {
        Map<Long,VoRuleCollectionAll> collectionAllMap = new HashMap<>();
        collItemMap.forEach((k,v)->{
            RcRuleCollection rcRuleCollection = collectionMap.get(k);
            Map<String,VoRuleAll> voRuleMap = new HashMap<>();
            v.forEach(item ->{
                //获取每一个规则集的配置项 list
                voRuleMap.put(item.getItemAlias(),ruleItemsMap.get(item.getRuleId()));
            });
            //组装vorulecollall
            VoRuleCollectionAll voRuleCollectionAll = new VoRuleCollectionAll();
            voRuleCollectionAll.setItems(voRuleMap);
            voRuleCollectionAll.setRcRuleCollection(rcRuleCollection);
            collectionAllMap.put(k,voRuleCollectionAll);
        });
        return collectionAllMap;
    }

    /**
     * 映射规则集与规则item
     *
     * @param collectionItems
     * @return
     */
    public Map<Long, List<RcRuleCollectionItem>> getCollItemMap(List<RcRuleCollectionItem> collectionItems) {
        Map<Long, List<RcRuleCollectionItem>> collItemMap = new HashMap<>();
        collectionItems.forEach(item -> {
            List<RcRuleCollectionItem> collectionItemList = collItemMap.get(item.getCollectionId());
            if (collectionItemList == null) {
                collectionItemList = new ArrayList<>();
            }
            collectionItemList.add(item);
            collItemMap.put(item.getCollectionId(), collectionItemList);
        });

        return collItemMap;
    }

    /**
     * 获取 rule id 与 rule item 的映射关系
     *
     * @param rcRuleItems
     * @return
     */
    public Map<Long, VoRuleAll> getLongListMap(List<RcRuleItem> rcRuleItems, Map<Long, RcRule> ruleIdMap) {
        // 手动创建映射 ruleid ruleItem
        Map<Long, VoRuleAll> ruleItemsMap = new HashMap<>();
        rcRuleItems.forEach(ruleItem -> {
            VoRuleAll voRuleAll = ruleItemsMap.get(ruleItem.getRuleId());
            if (voRuleAll == null) {
                voRuleAll = new VoRuleAll();
            }
            voRuleAll.setRcRule(ruleIdMap.get(ruleItem.getRuleId()));
            Map<String, RcRuleItem> rcRuleItemMap = new HashMap<>();
            rcRuleItemMap.put(ruleItem.getItemAlias(), ruleItem);
            voRuleAll.setItems(rcRuleItemMap);
            ruleItemsMap.put(ruleItem.getRuleId(), voRuleAll);
        });
        return ruleItemsMap;
    }

//    /**
//     * 获取规则集id和lis rule 的映射
//     *
//     * @param collectionItems
//     * @param ruleItemsMap
//     * @param ruleIdMap
//     * @return
//     */
//    public Map<Long, VoRuleCollectionAll> getRuleCollVoRuleMap(List<RcRuleCollectionItem> collectionItems, Map<Long, VoRuleAll> ruleItemsMap, Map<Long, VoRuleAll> ruleIdMap) {
//        // 创建规则集与voRule的映射
//        Map<Long, List<VoRule>> ruleCollVoRuleMap = new HashMap<>();
//        collectionItems.forEach(item -> {
//            List<VoRule> voRules = ruleCollVoRuleMap.get(item.getCollectionId());
//            if (voRules == null) {
//                voRules = new ArrayList<>();
//            }
//            VoRule voRule = new VoRule();
//            voRule.setRcRule(ruleIdMap.get(item.getRuleId()));
//            voRule.setRcRuleItem(ruleItemsMap.get(item.getRuleId()));
//            voRules.add(voRule);
//            ruleCollVoRuleMap.put(item.getCollectionId(), voRules);
//        });
//        return ruleCollVoRuleMap;
//    }


}
